package com.xbongbong.paas.script.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.constant.TimeConstant;
import com.xbongbong.paas.domain.entity.PaasFormEntity;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.factory.FieldOptimizationHandle;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.pojo.dto.PaymentExplainDTO;
import com.xbongbong.paas.redis.PaasRedisHelper;
import com.xbongbong.paas.redis.RedisPrefixConstant;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.JsonHelperUtil;
import com.xbongbong.pro.config.ProBaseConfig;
import com.xbongbong.pro.constant.I18nStringConstant;
import com.xbongbong.pro.constant.SymbolConstant;
import com.xbongbong.pro.constant.XbbProConstant;
import com.xbongbong.pro.enums.DistributorMarkEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.script.pojo.dto.FieldSetDTO;
import com.xbongbong.pro.script.pojo.dto.InitExplainDTO;
import com.xbongbong.saas.base.EnumBase;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.dao.WorkOrderExplainDao;
import com.xbongbong.saas.domain.entity.WorkOrderExplainEntity;
import com.xbongbong.saas.enums.SetTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.InvoiceEnum;
import com.xbongbong.saas.enums.business.PaymentEnum;
import com.xbongbong.saas.enums.business.PurchaseEnum;
import com.xbongbong.saas.enums.business.PurchaseInvoiceEnum;
import com.xbongbong.saas.enums.business.RefundEnum;
import com.xbongbong.saas.script.help.InitExplainsHelper;
import com.xbongbong.saas.script.tempenum.TempInvoiceEnum;
import com.xbongbong.saas.script.tempenum.TempPurchaseInvoiceEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.http.MediaType;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author：吴峰
 * @date: 2020/7/9 15:22
 * @Description：
 */
@RestController
@RequestMapping(XbbProConstant.API_ROOT_PREFIX + "/script/field")
public class FieldOptimizationScriptController {

    public static final Logger LOGGER = LoggerFactory.getLogger(FieldOptimizationScriptController.class);

    @Resource
    private ProBaseConfig proBaseConfig;
    @Resource
    private WorkOrderExplainDao workOrderExplainDao;
    @Resource
    private PaasRedisHelper paasRedisHelper;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;

    /**
     * 迁移的公司。不需要刷字段解释
     */
    private static final List<String> CORPID_SET = Arrays.asList("ding57a140520af3e0d735c2f4657eb6378f","ding92b11aac66268a5f35c2f4657eb6378f","ding1e51fde73f2b377935c2f4657eb6378f",
            "ding3314160aaf26759e35c2f4657eb6378f","ding73ec411f550becf535c2f4657eb6378f","ding1ab72f83081c0a2b35c2f4657eb6378f","ding2444195cb3f33c1435c2f4657eb6378f",
            "ding3d3857469210aba635c2f4657eb6378f","ding92205c195b0a88c4","ding43c72f5fdc751ecc","ding85c7b3602a830dbb35c2f4657eb6378f","dingf6db7c63f8b66f5135c2f4657eb6378f",
            "ding48d7d440f8c672ff35c2f4657eb6378f","ding93829086c3ad745035c2f4657eb6378f","dingb8565da5d48b58da35c2f4657eb6378f","dinge3fa697f86d461d2","dingc2edbdcd0ad63e51",
            "ding1bb0211b6d0bf53735c2f4657eb6378f","dingc499846e91cfaad435c2f4657eb6378f","dingf1dfefb795e1c99035c2f4657eb6378f","ding2b156389fd7819b735c2f4657eb6378f",
            "ding6be79508c5fe361935c2f4657eb6378f","ding617335704fbc8dce35c2f4657eb6378f","ding23b2d66c2321b8c135c2f4657eb6378f","ding4b546f4edbfb11db","ding890020a8b71c62f035c2f4657eb6378f",
            "dinge292e7be62a640d735c2f4657eb6378f","ding9ab8ee5bfe81d537","ding28043c7b889151f835c2f4657eb6378f","ding36032abc911708fd35c2f4657eb6378f","ding98d9c6fbacd05bdf35c2f4657eb6378f",
            "dingf4b6808664360de535c2f4657eb6378f","ding4b5c794e2aa066d135c2f4657eb6378f","ding6026dc2f6fce859b","ding6634a8cb51e502a0","dingd6597d3d073a24d1","dingae168b4f85a8f99c35c2f4657eb6378f",
            "dingc5349c03ab86d1be35c2f4657eb6378f","ding4b34f52155b5655135c2f4657eb6378f","ding7db782316151266835c2f4657eb6378f","ding9b806085453a1807","ding6cd2c844c08f9f5a35c2f4657eb6378f",
            "ding4c7b565ff2809fc235c2f4657eb6378f","dingf46bd02390ae1de635c2f4657eb6378f","ding97e8b187716a7c6935c2f4657eb6378f","ding06b10ab329bb5483","ding550e7a113b8529fb35c2f4657eb6378f",
            "ding5b4945428a96821435c2f4657eb6378f","ding423f4261b2259468","ding347ca8abdbe53c9235c2f4657eb6378f","ding7cb36d69473cef3c35c2f4657eb6378f","ding9033ea92888c486735c2f4657eb6378f",
            "ding2b432acc13eecf9535c2f4657eb6378f","ding8c2af5de681fdc0635c2f4657eb6378f","dinge3a3c26e78cdb45135c2f4657eb6378f","ding7b47cb6c2c05288235c2f4657eb6378f",
            "ding66fcc17632bb04d135c2f4657eb6378f","dingbc056cd6656b2080","dingc6b5b9f0619f69cd","dingda84deaeaf30b7f9","ding891381ef1585c3e135c2f4657eb6378f","ding5fd4daf6603fac9f35c2f4657eb6378f",
            "ding14d1ed0e1e53a32d35c2f4657eb6378f","ding7b1b5def2aa8432535c2f4657eb6378f","dingfe63368d1cc59bb7","ding703485b5b8e328f935c2f4657eb6378f","ding43d48bbec1c14ced35c2f4657eb6378f",
            "dingaeb2cb403885d0b0","ding2c4315ff35d3652d35c2f4657eb6378f","ding8bc86c3c300a22d1","ding8611875f9163eb1c35c2f4657eb6378f","ding09356ec62f6a63bb35c2f4657eb6378f","ding7d7048dadb92fc7f",
            "ding06a946ee942ad77e35c2f4657eb6378f","dingdc2c59388c30e2f635c2f4657eb6378f","ding738af671c1d09937","dingd234b55e851529fe35c2f4657eb6378f","ding6ab807ad56d60b7135c2f4657eb6378f",
            "ding30b7d78c50720a7835c2f4657eb6378f","ding640b1d1394189307","ding2d84787c2e9025b735c2f4657eb6378f","ding14248b8dfe7fb96f","dingb4b6e882080b731a35c2f4657eb6378f",
            "ding71d3012eca5d0dab35c2f4657eb6378f","ding0cf77a964237376935c2f4657eb6378f","ding191cf930926c2bb235c2f4657eb6378f","dingc83f94537db88d8835c2f4657eb6378f",
            "ding5b8f04ca4face53335c2f4657eb6378f","ding083cd45708b065ee35c2f4657eb6378f","ding13534ce92bb60d5a","dingec7550223670415c35c2f4657eb6378f","ding2b7fdc0571b56f9035c2f4657eb6378f",
            "dingd8eda606cdeed7e1","dinga2346ff985d6ce3635c2f4657eb6378f","ding0bdd5a9f5752923f35c2f4657eb6378f","ding1ac9a28f524f57d035c2f4657eb6378f","ding0bf64dd2ba063ca935c2f4657eb6378f",
            "ding9fea530fc34cd91a","ding56520d93f2a5026635c2f4657eb6378f","ding19c5f2b49d18e964","ding0167c409336f4a9735c2f4657eb6378f","dinga240a8787d5cc25d35c2f4657eb6378f",
            "ding18a5091c983313b135c2f4657eb6378f","ding8fdcf6ee06fa01eb","ding315661903fbaf62b35c2f4657eb6378f","dingc45df9402649cb4635c2f4657eb6378f","ding3361b563ec4af858","ding3ada9a199beb5e7435c2f4657eb6378f",
            "ding4addd2427ce581ff35c2f4657eb6378f","ding12c2bddd386825c4", "ding4af65b70753a0b50", "ding59b7345c945784b4", "ding52b435d92f7672a735c2f4657eb6378f", "dingd9c0a4802195775d",
            "dingf3a33e4726dc2bdb35c2f4657eb6378f","dingef35e6e78a61828f35c2f4657eb6378f","ding796815bfbdb4debe35c2f4657eb6378f","ding17efb38b293384cb35c2f4657eb6378f","ding69955bf6955a597935c2f4657eb6378f",
            "ding8c954e445a3fee4735c2f4657eb6378f","ding73ec411f550becf535c2f4657eb6378f","ding8b82dd8b0717b107","dingbfd3b0546f5e934b","dingafad392d3d57d44235c2f4657eb6378f","ding6de24f011671418e","dinga0c6935b1afbe1cc"
            );
    /**
     * 初始化非工单解释
     * @param fieldSetDTO
     * @return
     * @throws XbbException
     */
    @RequestMapping(value = "/optimization", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String optimization(@RequestBody @Valid FieldSetDTO fieldSetDTO) throws XbbException {
        if (!proBaseConfig.getXbbCode().equals(fieldSetDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        Long startTime = DateTimeUtil.getLong();
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(StringConstant.DEL, 0);
        param.put("startAddTime", fieldSetDTO.getStartAddTime());
        param.put("endAddTime", fieldSetDTO.getEndAddTime());
        // 迁移公司不需要刷explain
        param.put("corpidNotIn", CORPID_SET);
        if (CollectionsUtil.isNotEmpty(fieldSetDTO.getCorpidList())) {
            param.put("corpidIn", fieldSetDTO.getCorpidList());
        }
        param.put("explainNotEmpty", 1);
        Integer allTotal = paasFormExplainModel.getEntitysCount(param);
        LOGGER.info("共：" + allTotal + "条");
        Integer pageSize = 100;
        Integer index = allTotal/pageSize + 1;
        Long page = 0L;
        for (int j = 0; j < index; j++) {
            param.clear();
            param.put(StringConstant.DEL, 0);
            param.put("startAddTime", fieldSetDTO.getStartAddTime());
            param.put("endAddTime", fieldSetDTO.getEndAddTime());
            // 迁移公司不需要刷explain
            param.put("corpidNotIn", CORPID_SET);
            if (CollectionsUtil.isNotEmpty(fieldSetDTO.getCorpidList())) {
                param.put("corpidIn", fieldSetDTO.getCorpidList());
            }
            if (CollectionsUtil.isNotEmpty(fieldSetDTO.getFormIdList())) {
                param.put("formIdIn", fieldSetDTO.getFormIdList());
            }
            param.put("idGte", page);
            param.put("pageSize", pageSize);
            param.put("explainNotEmpty", 1);
            param.put("orderByStr", "id ASC");
            Integer pageNum = j+1;
            LOGGER.info("搜索第 "+ pageNum + " 页" + "id为："+page);
            List<PaasFormExplainEntity> explainList = paasFormExplainModel.getNoHandleExplainsByFindEntitys(param);
            if (CollectionsUtil.isNotEmpty(explainList)) {
                LOGGER.info("更新第 " + pageNum + " 页");
                Integer total = explainList.size();
                page = explainList.get(total-1).getId();
                List<PaasFormExplainEntity> resultList = new ArrayList<>();
                for (PaasFormExplainEntity item : explainList) {
                    if (CORPID_SET.contains(item.getCorpid())) {
                        // 迁移公司不需要刷explain
                        continue;
                    }
                    List<FieldAttrEntity> fieldList = JSON.parseArray(item.getExplains(), FieldAttrEntity.class);
                    if (CollectionsUtil.isNotEmpty(fieldList)) {
                        Long id = item.getId();
                        // 字段处理封装
                        FieldOptimizationHandle.fieldHandle(fieldList);
                        PaasFormExplainEntity paasFormExplainEntity = new PaasFormExplainEntity();
                        paasFormExplainEntity.setId(id);
                        paasFormExplainEntity.setUpdateTime(DateTimeUtil.getInt());
                        paasFormExplainEntity.setExplains(JSON.toJSONString(fieldList));
                        resultList.add(paasFormExplainEntity);
                    }
                }
                if (CollectionsUtil.isNotEmpty(resultList)) {
                    paasFormExplainModel.updateBatch(resultList, null);
                }
            }
        }
        Long endTime = DateTimeUtil.getLong();
        Long num = endTime - startTime;
        LOGGER.info(allTotal+"条字段解释，explain简化花费时间：" + num);
        JSONObject object = new JSONObject();
        object.put("success", "成功");
        return object.toJSONString();
    }


    /**
     * 初始化工单解释
     * @param fieldSetDTO
     * @return
     * @throws XbbException
     */
    @RequestMapping(value = "/optimization/workOrder", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String optimizationWorkOrder(@RequestBody @Valid FieldSetDTO fieldSetDTO) throws XbbException {
        if (!proBaseConfig.getXbbCode().equals(fieldSetDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        Long startTime = DateTimeUtil.getLong();
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(StringConstant.DEL, 0);
        param.put("startAddTime", fieldSetDTO.getStartAddTime());
        param.put("endAddTime", fieldSetDTO.getEndAddTime());
        // 迁移公司不需要刷explain
        param.put("corpidNotIn", CORPID_SET);
        if (CollectionsUtil.isNotEmpty(fieldSetDTO.getCorpidList())) {
            param.put("corpidIn", fieldSetDTO.getCorpidList());
        }
        param.put("explainNotEmpty", 1);
        Integer allTotal = workOrderExplainDao.getEntitysCount(param);
        LOGGER.info("共：" + allTotal + "条");
        Integer pageSize = 100;
        Integer index = allTotal/pageSize + 1;
        Long page = 0L;
        for (int j = 0; j < index; j++) {
            param.clear();
            param.put(StringConstant.DEL, 0);
            param.put("startAddTime", fieldSetDTO.getStartAddTime());
            param.put("endAddTime", fieldSetDTO.getEndAddTime());
            // 迁移公司不需要刷explain
            param.put("corpidNotIn", CORPID_SET);
            if (CollectionsUtil.isNotEmpty(fieldSetDTO.getCorpidList())) {
                param.put("corpidIn", fieldSetDTO.getCorpidList());
            }
            if (CollectionsUtil.isNotEmpty(fieldSetDTO.getFormIdList())) {
                param.put("formIdIn", fieldSetDTO.getFormIdList());
            }

            param.put("idGte", page);
            param.put("pageSize", pageSize);
            param.put("explainNotEmpty", 1);
            param.put("orderByStr", "id ASC");
            Integer pageNum = j+1;
            LOGGER.info("搜索第 "+ pageNum + " 页" + "id为："+page);
            List<WorkOrderExplainEntity> explainList = workOrderExplainDao.findEntitys(param);
            if (CollectionsUtil.isNotEmpty(explainList)) {
                LOGGER.info("更新第 " + pageNum + " 页");
                Integer total = explainList.size();
                page = explainList.get(total-1).getId();
                List<WorkOrderExplainEntity> resultList = new ArrayList<>();
                for (WorkOrderExplainEntity item : explainList) {
                    if (CORPID_SET.contains(item.getCorpid())) {
                        // 迁移公司不需要刷explain
                        continue;
                    }
                    List<FieldAttrEntity> fieldList = JSON.parseArray(item.getExplains(), FieldAttrEntity.class);
                    if (CollectionsUtil.isNotEmpty(fieldList)) {
                        Long id = item.getId();
                        // 字段处理封装
                        FieldOptimizationHandle.fieldHandle(fieldList);
                        WorkOrderExplainEntity paasFormExplainEntity = new WorkOrderExplainEntity();
                        paasFormExplainEntity.setId(id);
                        paasFormExplainEntity.setUpdateTime(DateTimeUtil.getInt());
                        paasFormExplainEntity.setExplains(JSON.toJSONString(fieldList));
                        resultList.add(paasFormExplainEntity);
                    }
                }
                if (CollectionsUtil.isNotEmpty(resultList)) {
                    workOrderExplainDao.updateBatch(resultList, null);
                }

            }
        }
        Long endTime = DateTimeUtil.getLong();
        Long num = endTime - startTime;
        LOGGER.info(allTotal+"条工单字段解释，工单explain花费时间：" + num);
        JSONObject object = new JSONObject();
        object.put("success", "成功");
        return object.toJSONString();
    }

    @RequestMapping(value = "/initExplain", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String initExplain(@RequestBody @Valid InitExplainDTO initExplainDTO) throws XbbException {
        if (!proBaseConfig.getXbbCode().equals(initExplainDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        LocaleContextHolder.setLocale(Locale.CHINA);

        List<Integer> exceptWorkOrderList = Arrays.asList(
        );
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(StringConstant.DEL, 0);
        param.put(StringConstant.CORPID, "0");
        param.put("businessTypeIn", exceptWorkOrderList);

        List<PaasFormExplainEntity> explainList = paasFormExplainModel.getNoHandleExplainsByFindEntitys(param);
        Map<Integer, PaasFormExplainEntity> updateExplainMap = new HashMap<>(explainList.size());
        explainList.forEach(item->{
            updateExplainMap.put(item.getBusinessType(), item);
        });
        List<PaasFormExplainEntity> insertExplainList = new ArrayList<>();
        List<PaasFormExplainEntity> updateExplainList = new ArrayList<>();
        PaasFormEntity productForm = new PaasFormEntity(0L, 0L, 0L, SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.PRODUCT.getCode());
        for (Integer item : exceptWorkOrderList) {
            String alias = XbbRefTypeEnum.getByCode(item).getAlias();
            List<FieldAttrEntity> fieldList = InitExplainsHelper.initFieldAttrEntity(alias, productForm, null, 0);
            long now = DateTimeUtil.getInt();
            if (Objects.equals(XbbRefTypeEnum.WORK_ORDER.getCode(), item)) {
                continue;
            }
            if (updateExplainMap.containsKey(item)) {
                PaasFormExplainEntity paasFormExplainEntity = new PaasFormExplainEntity();
                paasFormExplainEntity.setId(updateExplainMap.get(item).getId());
                paasFormExplainEntity.setExplains(JSON.toJSONString(fieldList));
                paasFormExplainEntity.setBusinessType(item);
                updateExplainList.add(paasFormExplainEntity);
            } else {
                PaasFormExplainEntity paasFormExplainEntity = new PaasFormExplainEntity("0", 0L, 0L, 0L, 1,
                        JSON.toJSONString(fieldList), "1", now, now, DelEnum.NORMAL.getDel(), SaasMarkEnum.SAAS.getCode(), item, DistributorMarkEnum.OTHER.getCode());
                insertExplainList.add(paasFormExplainEntity);
            }
        }
        if (CollectionsUtil.isNotEmpty(updateExplainList)) {
            paasFormExplainModel.updateBatchExplains(updateExplainList);
            updateExplainList.forEach(item->{
                String key = "0" + StringConstant.UNDER_LINE + item.getBusinessType();
                String explains = item.getExplains();
                paasRedisHelper.setValue(RedisPrefixConstant.FIELD_EXPLANATION, key, explains, TimeConstant.SECONDS_PER_DAY);
            });
        }
        if (CollectionsUtil.isNotEmpty(insertExplainList)) {
            paasFormExplainModel.insertBatch(insertExplainList);
            insertExplainList.forEach(item->{
                String key = "0" + StringConstant.UNDER_LINE + item.getBusinessType();
                String explains = item.getExplains();
                paasRedisHelper.setValue(RedisPrefixConstant.FIELD_EXPLANATION, key, explains, TimeConstant.SECONDS_PER_DAY);
            });
        }
        param.clear();
        param.put(StringConstant.DEL, 0);
        param.put(StringConstant.CORPID, "0");
        param.put(StringConstant.FORM_ID, 0);


        List<WorkOrderExplainEntity> workOrderList = workOrderExplainDao.findEntitys(param);

        if (CollectionsUtil.isEmpty(workOrderList)) {
            List<FieldAttrEntity> fieldList = InitExplainsHelper.initFieldAttrEntity(XbbRefTypeEnum.WORK_ORDER.getAlias(), productForm, null, 0);
            long now = DateTimeUtil.getInt();
            WorkOrderExplainEntity insertWorkOrder = new WorkOrderExplainEntity("0", 0L, 0L, 0L,
                    JSON.toJSONString(fieldList), "1", now, now, DelEnum.NORMAL.getDel());
            paasRedisHelper.setValue(RedisPrefixConstant.FIELD_EXPLANATION, StringConstant.DEFAULT_CORPID + XbbRefTypeEnum.WORK_ORDER.getCode(), insertWorkOrder.getExplains(), TimeConstant.SECONDS_PER_DAY);
            workOrderExplainDao.insert(insertWorkOrder);
        } else {
            List<FieldAttrEntity> fieldList = InitExplainsHelper.initFieldAttrEntity(XbbRefTypeEnum.WORK_ORDER.getAlias(), productForm, null, 0);
            List<WorkOrderExplainEntity> updateWorkOrderList = new ArrayList<>();
            workOrderList.forEach(item->{
                WorkOrderExplainEntity workOrderExplainEntity = new WorkOrderExplainEntity();
                workOrderExplainEntity.setId(item.getId());
                workOrderExplainEntity.setExplains(JSON.toJSONString(fieldList));
                updateWorkOrderList.add(workOrderExplainEntity);
            });
            workOrderExplainDao.updateBatch(updateWorkOrderList, "0");
            workOrderList.forEach(item->{
                String key = "0" + StringConstant.UNDER_LINE + XbbRefTypeEnum.WORK_ORDER.getCode();
                String explains = item.getExplains();
                paasRedisHelper.setValue(RedisPrefixConstant.FIELD_EXPLANATION, key, explains, TimeConstant.SECONDS_PER_DAY);
            });
        }

        JSONObject object = new JSONObject();
        object.put("success", "成功");
        return object.toJSONString();
    }

    /**
     * 处理或初始化corpid = "0" 的默认解释
     * 注：
     * （1）参照上面老哥写的initExplain方法写该方法
     * （2）不包含工单，及产品相关表单解释处理
     * @param initExplainDTO
     * @return java.lang.String
     * @throws XbbException
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    @RequestMapping(value = "/initDefaultExplain", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String initDefaultExplain(@RequestBody @Valid InitExplainDTO initExplainDTO) throws XbbException {
        if (!proBaseConfig.getXbbCode().equals(initExplainDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        LOGGER.info("-----------/pro/v1/script/field/initDefaultExplain begin-----------");
        long timeStart = DateTimeUtil.getInt();
        LocaleContextHolder.setLocale(Locale.CHINA);
        List<Integer> distributorBusinessList = initExplainDTO.getDistributorBusinessList();
        List<Integer> otherBusinessList = initExplainDTO.getBusinessList();
        //不能都为空
        if (CollectionsUtil.isEmpty(distributorBusinessList) && CollectionsUtil.isEmpty(otherBusinessList)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100002, "请传入要处理的业务类型");
        } else if (Objects.isNull(distributorBusinessList)) {
            distributorBusinessList = new ArrayList<>();
        } else if (Objects.isNull(otherBusinessList)) {
            otherBusinessList = new ArrayList<>();
        }
        Set<Integer> allBusinessTypeSet = new HashSet<>();
        allBusinessTypeSet.addAll(distributorBusinessList);
        allBusinessTypeSet.addAll(otherBusinessList);
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(StringConstant.DEL, 0);
        param.put(StringConstant.CORPID, BasicConstant.ZERO_STRING);
        param.put("businessTypeIn", allBusinessTypeSet);
        List<PaasFormExplainEntity> explainList = paasFormExplainModel.getNoHandleExplainsByFindEntitys(param);
        /**
         * explainList未限制distributorMark，查出每种业务可能有多(两)份，因此updateExplainMap的key要拼上distributorMark
         * key：businessType_distributorMark
         */
        Map<String, PaasFormExplainEntity> updateExplainMap = explainList.stream().collect(Collectors.toMap(s -> String.format(SymbolConstant.UNDERLINE_PLACE, s.getBusinessType(), s.getDistributorMark()), Function.identity()));
        List<PaasFormExplainEntity> insertExplainList = new ArrayList<>();
        List<PaasFormExplainEntity> updateExplainList = new ArrayList<>();
        DistributorMarkEnum distributorMarkEnum = DistributorMarkEnum.DISTRIBUTOR;
        DistributorMarkEnum otherMarkEnum = DistributorMarkEnum.OTHER;
        long now = DateTimeUtil.getInt();
        for (Integer item : allBusinessTypeSet) {
            if (Objects.equals(XbbRefTypeEnum.WORK_ORDER.getCode(), item)) {
                continue;
            }
            XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(item);
            //经销商模板
            setExplainEntity(distributorBusinessList, updateExplainMap, insertExplainList, updateExplainList, distributorMarkEnum, now, xbbRefTypeEnum);
            //普通非经销商模板
            setExplainEntity(otherBusinessList, updateExplainMap, insertExplainList, updateExplainList, otherMarkEnum, now, xbbRefTypeEnum);
        }
        if (CollectionsUtil.isNotEmpty(updateExplainList)) {
            paasFormExplainModel.updateBatchExplains(updateExplainList);
            //解释置入缓存
            setExplainToRedis(updateExplainList);
        }
        if (CollectionsUtil.isNotEmpty(insertExplainList)) {
            paasFormExplainModel.insertBatch(insertExplainList);
            setExplainToRedis(insertExplainList);
        }
        LOGGER.info("-----------time end:" + (DateTimeUtil.getInt() - timeStart));
        LOGGER.info("-----------/pro/v1/script/field/initDefaultExplain over");
        JSONObject object = new JSONObject();
        object.put("success", "成功");
        return object.toJSONString();
    }

    /**
     * 初始化工单解释
     * @param fieldSetDTO
     * @return
     * @throws XbbException
     */
    @RequestMapping(value = "/optimization/comboNum", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String optimizationcomboNum(@RequestBody @Valid FieldSetDTO fieldSetDTO) throws XbbException {
        if (!proBaseConfig.getXbbCode().equals(fieldSetDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        LOGGER.info("开始执行");
        Long startTime = DateTimeUtil.getLong();
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(StringConstant.DEL, 0);
        param.put("startAddTime", fieldSetDTO.getStartAddTime());
        param.put("endAddTime", fieldSetDTO.getEndAddTime());
        if (CollectionsUtil.isNotEmpty(fieldSetDTO.getCorpidList())) {
            param.put("corpidIn", fieldSetDTO.getCorpidList());
        }
        List<Integer> businessType = Arrays.asList(XbbRefTypeEnum.COMMUNICATE_PLAN.getCode(), XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), XbbRefTypeEnum.CONTRACT.getCode(),
                XbbRefTypeEnum.INVOICE.getCode(), XbbRefTypeEnum.PAYMENT.getCode(), XbbRefTypeEnum.PAY_PLAN.getCode(), XbbRefTypeEnum.PURCHASE_INVOICE.getCode(),
                XbbRefTypeEnum.QUOTATION.getCode(), XbbRefTypeEnum.REFUND.getCode(), XbbRefTypeEnum.RETURNED_PURCHASE.getCode(), XbbRefTypeEnum.SALES_OPPORTUNITY.getCode());
        param.put("businessTypeIn", businessType);
        Integer allTotal = paasFormExplainModel.getEntitysCount(param);
        LOGGER.info("共：" + allTotal + "条");
        Integer pageSize = 100;
        Integer index = allTotal/pageSize + 1;
        Long page = 0L;
        for (int j = 0; j < index; j++) {
            param.clear();
            param.put(StringConstant.DEL, 0);
            param.put("startAddTime", fieldSetDTO.getStartAddTime());
            param.put("endAddTime", fieldSetDTO.getEndAddTime());
            if (CollectionsUtil.isNotEmpty(fieldSetDTO.getCorpidList())) {
                param.put("corpidIn", fieldSetDTO.getCorpidList());
            }
            param.put("businessTypeIn", businessType);
            param.put("idGte", page);
            param.put("pageSize", pageSize);
            param.put("orderByStr", "id ASC");
            Integer pageNum = j+1;
            LOGGER.info("搜索第 "+ pageNum + " 页" + "共："+index+"页");
            List<PaasFormExplainEntity> explainList = paasFormExplainModel.getNoHandleExplainsByFindEntitys(param);
            if (CollectionsUtil.isNotEmpty(explainList)) {

                Integer total = explainList.size();
                page = explainList.get(total-1).getId();
                List<PaasFormExplainEntity> resultList = new ArrayList<>();
                for (PaasFormExplainEntity item : explainList) {

                    List<FieldAttrEntity> fieldList = JSON.parseArray(item.getExplains(), FieldAttrEntity.class);
                    if (CollectionsUtil.isNotEmpty(fieldList)) {
                        Long id = item.getId();
                        // 字段处理封装
                        fieldList.forEach(fieldAttrEntity->{
                            if (Objects.equals(FieldTypeEnum.COMBO_NUM.getType(), fieldAttrEntity.getFieldType())) {
//                                String alias = XbbRefTypeEnum.getByCode(item.getBusinessType()).getAlias();
//
//                                String aliasEnum = "Temp" + alias.substring(0, 1).toUpperCase() + alias.substring(1, alias.length()) + "Enum";
//                                // 拼装包名
//                                String className = "com.xbongbong.saas.script.tempenum." + aliasEnum;
//                                // 根据包名拿到对象
//                                try {
//                                    String saasAttr = fieldAttrEntity.getSaasAttr();
//                                    Class clazz = Class.forName(className);
//                                    // 获取getAllEnum方法
//                                    Method method = clazz.getMethod("getAllEnum");
//                                    List<Object> list = (List<Object>) method.invoke(clazz);
//                                    List<String> enumAttrs = null;
//                                    for (Object object : list) {
//                                        // 根据方法getAnEnum拿到对应的枚举类
//                                        Method nameMethod = object.getClass().getMethod("getAnEnum");
//                                        Object anEnum = nameMethod.invoke(object);
//                                        // 包装业务枚举类
//                                        EnumBase<Object> enumBase = new EnumBase<>(anEnum);
//                                        Class<?> enumBaseClazz = enumBase.t.getClass();
//                                        if (enumAttrs == null) {
//                                            // 获取业务枚举类中的属性，以集合的形式返回，同一个枚举的属性值只获取一次
//                                            enumAttrs = InitExplainsHelper.getBusinessEnumAttrs(enumBaseClazz);
//                                        }
//                                        FieldAttrEntity field = InitExplainsHelper.setField(enumBase, enumAttrs);
//                                        if (Objects.equals(field.getSaasAttr(), saasAttr)) {
//                                            // 获取getAllEnum方法
//                                            String attr = saasAttr.substring(0, 1).toUpperCase() + saasAttr.substring(1);
//                                            String methodName = "init" + attr;
//                                            Method methodHasParameter = clazz.getMethod(methodName, FieldAttrEntity.class);
//                                            methodHasParameter.invoke(enumBase, field);
//                                            System.out.println(field);
//                                            fieldAttrEntity.setItems(field.getItems());
//                                        }
//                                    }
//
//                                } catch (Exception e) {
//                                    e.printStackTrace();
//
//                                }
                                fieldAttrEntity.setItems(null);
                            }
                        });
                        PaasFormExplainEntity paasFormExplainEntity = new PaasFormExplainEntity();
                        paasFormExplainEntity.setId(id);
                        paasFormExplainEntity.setUpdateTime(DateTimeUtil.getInt());
                        paasFormExplainEntity.setExplains(JSON.toJSONString(fieldList));
                        resultList.add(paasFormExplainEntity);
                    }
                }
                if (CollectionsUtil.isNotEmpty(resultList)) {
                    paasFormExplainModel.updateBatch(resultList, null);
                    LOGGER.info("更新完第 " + pageNum + " 页" + "共："+index+"页");
                }

            }
        }
        Long endTime = DateTimeUtil.getLong();
        Long num = endTime - startTime;
        LOGGER.info(allTotal+"条字段解释，explain花费时间：" + num);
        JSONObject object = new JSONObject();
        object.put("success", "成功");
        object.put("time", num);
        return object.toJSONString();
    }

    /**
     * 设置经销商/非经销商 corpid=0 的模板解释
     * @param businessList 业务list
     * @param updateExplainMap key：businessType_distributorMark；value：字段解释实体
     * @param insertExplainList 要插入的解释
     * @param updateExplainList 要更新的解释
     * @param distributorMarkEnum 经销商mark标识
     * @param now 时间
     * @param xbbRefTypeEnum 业务类型
     * @throws XbbException
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    private void setExplainEntity(List<Integer> businessList, Map<String, PaasFormExplainEntity> updateExplainMap, List<PaasFormExplainEntity> insertExplainList, List<PaasFormExplainEntity> updateExplainList, DistributorMarkEnum distributorMarkEnum, long now, XbbRefTypeEnum xbbRefTypeEnum) throws XbbException {
        int businessType = xbbRefTypeEnum.getCode();
        if (businessList.contains(businessType)) {
            //key：businessType_distributorMark
            String keyOther = String.format(SymbolConstant.UNDERLINE_PLACE, businessType, distributorMarkEnum.getCode());
            List<FieldAttrEntity> fieldList;
            boolean isProductForm  = Objects.equals(businessType, XbbRefTypeEnum.CUSTOMER_STATEMENT.getCode()) || Objects.equals(businessType,XbbRefTypeEnum.PURCHASE.getCode()) || Objects.equals(businessType,XbbRefTypeEnum.REFUND.getCode());
            if (isProductForm) {
                fieldList = InitExplainsHelper.initFieldAttrEntity(xbbRefTypeEnum.getAlias(), new PaasFormEntityExt(), null, distributorMarkEnum.getCode());
            } else {
                fieldList = InitExplainsHelper.initFieldAttrEntity(xbbRefTypeEnum.getAlias(), null, null, distributorMarkEnum.getCode());
            }
            if (updateExplainMap.containsKey(keyOther)) {
                PaasFormExplainEntity paasFormExplainEntity = new PaasFormExplainEntity();
                paasFormExplainEntity.setId(updateExplainMap.get(keyOther).getId());
                paasFormExplainEntity.setExplains(JSON.toJSONString(fieldList));
                paasFormExplainEntity.setBusinessType(businessType);
                paasFormExplainEntity.setUpdateTime(now);
                paasFormExplainEntity.setDistributorMark(distributorMarkEnum.getCode());
                updateExplainList.add(paasFormExplainEntity);
            } else {
                PaasFormExplainEntity paasFormExplainEntity = new PaasFormExplainEntity("0", 0L, 0L, 0L, 1, JSON.toJSONString(fieldList), "1", now, now, DelEnum.NORMAL.getDel(), SaasMarkEnum.SAAS.getCode(), businessType, distributorMarkEnum.getCode());
                insertExplainList.add(paasFormExplainEntity);
            }
        }
    }

    /**
     * 把corpid=0的解释置入缓存
     * @param explainList
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    private void setExplainToRedis(List<PaasFormExplainEntity> explainList) {
        explainList.forEach(item -> {
            //默认解释缓存key："0"_businessType_distributorMark
            StringBuilder key = new StringBuilder();
            key.append(BasicConstant.ZERO_STRING);
            key.append(SymbolConstant.UNDERLINE);
            key.append(item.getBusinessType());
            key.append(SymbolConstant.UNDERLINE);
            key.append(item.getDistributorMark());
            String explains = item.getExplains();
            paasRedisHelper.setValue(RedisPrefixConstant.FIELD_EXPLANATION, key.toString(), explains, TimeConstant.SECONDS_PER_DAY);
        });
    }

    public static void main(String[] args) {
        String alias = XbbRefTypeEnum.getByCode(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode()).getAlias();

        String aliasEnum = "Temp" + alias.substring(0, 1).toUpperCase() + alias.substring(1, alias.length()) + "Enum";
        // 拼装包名
        String className = "com.xbongbong.saas.script.tempenum." + aliasEnum;
        // 根据包名拿到对象
        try {
            Class clazz = Class.forName(className);
            // 获取getAllEnum方法
            Method method = clazz.getMethod("getAllEnum");
            List<Object> list = (List<Object>) method.invoke(clazz);
            List<String> enumAttrs = null;
            for (Object object : list) {
                // 根据方法getAnEnum拿到对应的枚举类
                Method nameMethod = object.getClass().getMethod("getAnEnum");
                Object anEnum = nameMethod.invoke(object);
                // 包装业务枚举类
                EnumBase<Object> enumBase = new EnumBase<>(anEnum);
                Class<?> enumBaseClazz = enumBase.t.getClass();
                if (enumAttrs == null) {
                    // 获取业务枚举类中的属性，以集合的形式返回，同一个枚举的属性值只获取一次
                    enumAttrs = InitExplainsHelper.getBusinessEnumAttrs(enumBaseClazz);
                }
                FieldAttrEntity field = InitExplainsHelper.setField(enumBase, enumAttrs);
                String saasAttr = "isPublic";
                if (Objects.equals(field.getSaasAttr(), saasAttr)) {
                    // 获取getAllEnum方法
                    String attr = saasAttr.substring(0, 1).toUpperCase() + saasAttr.substring(1);
                    String methodName = "init" + attr;
                    Method methodHasParameter = clazz.getMethod(methodName, FieldAttrEntity.class);
                    methodHasParameter.invoke(enumBase, field);
                    System.out.println(field);
                    continue;
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }




    @RequestMapping(value = "/initmarketExplain", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String initmarketExplain(@RequestBody @Valid InitExplainDTO initExplainDTO) throws XbbException {
        if (!proBaseConfig.getXbbCode().equals(initExplainDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        LOGGER.warn("-------------initmarketExplain begin-----------");
        long start = DateTimeUtil.getInt();
        LocaleContextHolder.setLocale(Locale.CHINA);

        List<Integer> exceptWorkOrderList = Arrays.asList(
                XbbRefTypeEnum.MARKETING_ACTIVITY_MANAGEMENT.getCode(),
                XbbRefTypeEnum.PROMOTION_ACTIVITY_MANAGEMENT.getCode(),
                XbbRefTypeEnum.WRITE_OFF_RECORD.getCode()
        );
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(StringConstant.DEL, 0);
        param.put(StringConstant.CORPID, "0");
        param.put("businessTypeIn", exceptWorkOrderList);

        List<PaasFormExplainEntity> explainList = paasFormExplainModel.getNoHandleExplainsByFindEntitys(param);
        Map<Integer, PaasFormExplainEntity> updateExplainMap = new HashMap<>(explainList.size());
        explainList.forEach(item->{
            updateExplainMap.put(item.getBusinessType(), item);
        });
        List<PaasFormExplainEntity> insertExplainList = new ArrayList<>();
        List<PaasFormExplainEntity> updateExplainList = new ArrayList<>();
        PaasFormEntity productForm = new PaasFormEntity(0L, 0L, 0L, SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.PRODUCT.getCode());
        for (Integer item : exceptWorkOrderList) {
            String alias = XbbRefTypeEnum.getByCode(item).getAlias();
            List<FieldAttrEntity> fieldList = InitExplainsHelper.initFieldAttrEntity(alias, productForm, null, 0);
            long now = DateTimeUtil.getInt();
            if (updateExplainMap.containsKey(item)) {
                PaasFormExplainEntity paasFormExplainEntity = new PaasFormExplainEntity();
                paasFormExplainEntity.setId(updateExplainMap.get(item).getId());
                paasFormExplainEntity.setExplains(JSON.toJSONString(fieldList));
                paasFormExplainEntity.setBusinessType(item);
                paasFormExplainEntity.setDistributorMark(DistributorMarkEnum.DISTRIBUTOR.getCode());
                updateExplainList.add(paasFormExplainEntity);
            } else {
                PaasFormExplainEntity paasFormExplainEntity = new PaasFormExplainEntity("0", 0L, 0L, 0L, 1,
                        JSON.toJSONString(fieldList), "1", now, now, DelEnum.NORMAL.getDel(), SaasMarkEnum.SAAS.getCode(), item, DistributorMarkEnum.DISTRIBUTOR.getCode());
                insertExplainList.add(paasFormExplainEntity);
            }
        }
        if (CollectionsUtil.isNotEmpty(updateExplainList)) {
            paasFormExplainModel.updateBatchExplains(updateExplainList);
            updateExplainList.forEach(item->{
                String key = "0" + StringConstant.UNDER_LINE + item.getBusinessType()+ StringConstant.UNDER_LINE + DistributorMarkEnum.DISTRIBUTOR;
                String explains = item.getExplains();
                paasRedisHelper.setValue(RedisPrefixConstant.FIELD_EXPLANATION, key, explains, TimeConstant.SECONDS_PER_DAY);
            });
        }
        if (CollectionsUtil.isNotEmpty(insertExplainList)) {
            paasFormExplainModel.insertBatch(insertExplainList);
            insertExplainList.forEach(item->{
                String key = "0" + StringConstant.UNDER_LINE + item.getBusinessType()+ StringConstant.UNDER_LINE + DistributorMarkEnum.DISTRIBUTOR;
                String explains = item.getExplains();
                paasRedisHelper.setValue(RedisPrefixConstant.FIELD_EXPLANATION, key, explains, TimeConstant.SECONDS_PER_DAY);
            });
        }
        JSONObject object = new JSONObject();
        object.put("success", "成功");
        LOGGER.warn("consume:" + (DateTimeUtil.getInt() - start));
        LOGGER.warn("-------------initmarketExplain over-----------");
        return object.toJSONString();
    }

    /**
     * 更新数据库里面应收金额描述字段
     * @param paymentExplainDTO
     * @return
     * @throws XbbException
     */
    @RequestMapping(value = "/initPaymentAmountMemoExplain", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String initPaymentAmountMemoExplain(@RequestBody @Valid PaymentExplainDTO paymentExplainDTO) throws XbbException {
        if (!proBaseConfig.getXbbCode().equals(paymentExplainDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        LOGGER.warn("-------------initPaymentAmountMemoExplain begin-----------");
        long start = DateTimeUtil.getInt();
        LocaleContextHolder.setLocale(Locale.CHINA);

        //每次查询500条
        Long idGte = 0L;
        Integer startId = 0;
        Integer pageNum = 500;
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(StringConstant.DEL, 0);
        param.put("businessType", XbbRefTypeEnum.PAYMENT.getCode());
        param.put("start", startId);
        param.put("pageNum", pageNum);
        param.put("orderByStr", "id asc");
        while (true){
            param.put("idGte", idGte);
            //获取要处理的数据
            List<PaasFormExplainEntity> paymentExplainList = paasFormExplainModel.getNoHandleExplainsByFindEntitys(param);
            List<PaasFormExplainEntity> updatePaasFormExplainList = new ArrayList<>();
            LOGGER.warn("处理进度：已处理到 tb_paas_form_explain.id " + idGte);
            if (CollectionUtils.isEmpty(paymentExplainList)) {
                break;
            }
            paymentExplainList.forEach(item -> {
                if(!Objects.equals("[]",item.getExplains())){
                    List<FieldAttrEntity> fieldList = JsonHelperUtil.parseArray(item.getExplains(), FieldAttrEntity.class);
                    fieldList.forEach(field -> {
                        if (Objects.equals(field.getAttr(),PaymentEnum.AMOUNT.getAttr()) && StringUtils.isEmpty(field.getMemo())){
                            field.setMemo(I18nMessageUtil.getMessage(I18nStringConstant.AMOUNT_MEMO));
                            item.setExplains(JSON.toJSONString(fieldList));
                            updatePaasFormExplainList.add(item);
                        }
                    });
                }
            });
            if (!CollectionUtils.isEmpty(updatePaasFormExplainList)){
                paasFormExplainModel.updateBatchExplains(updatePaasFormExplainList);
            }
            idGte = paymentExplainList.get(paymentExplainList.size() - 1).getId();
        }
        JSONObject object = new JSONObject();
        object.put("success", "成功");
        LOGGER.warn("consume:" + (DateTimeUtil.getInt() - start));
        LOGGER.warn("-------------initPaymentAmountMemoExplain over-----------");
        return object.toJSONString();
    }

    /**
     * 修复数据库里面应收金额描述字段
     * @param paymentExplainDTO
     * @return
     * @throws XbbException
     */
    @RequestMapping(value = "/repairInvoiceItemsExplain", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String repairInvoiceItemsExplain(@RequestBody @Valid PaymentExplainDTO paymentExplainDTO) throws XbbException {
        if (!proBaseConfig.getXbbCode().equals(paymentExplainDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        LOGGER.warn("-------------repairInvoiceItemsExplain begin-----------");
        long start = DateTimeUtil.getInt();
        LocaleContextHolder.setLocale(Locale.CHINA);

        //每次查询300条
        Long idGte = 0L;
        Integer startId = 0;
        Integer pageNum = 300;
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(StringConstant.DEL, 0);
        param.put("businessTypeIn",Arrays.asList(XbbRefTypeEnum.INVOICE.getCode(),XbbRefTypeEnum.PURCHASE_INVOICE.getCode()));
        Long maxId = paasFormExplainModel.getMaxId(param);
        param.put("start", startId);
        param.put("pageNum", pageNum);
        param.put("orderByStr", "id asc");
        while (true){
            param.put("idGte", idGte);
            //获取要处理的数据
            List<PaasFormExplainEntity> explainList = paasFormExplainModel.getNoHandleExplainsByFindEntitys(param);
            List<PaasFormExplainEntity> updatePaasFormExplainList = new ArrayList<>();
            LOGGER.warn("处理进度：已处理到 tb_paas_form_explain.id " + idGte + " / " + maxId);
            if (CollectionUtils.isEmpty(explainList)) {
                break;
            }
            explainList.forEach(item -> {
                Integer businessType = item.getBusinessType();
                if(!Objects.equals("[]",item.getExplains())){
                    List<FieldAttrEntity> fieldList = JsonHelperUtil.parseArray(item.getExplains(), FieldAttrEntity.class);
                    boolean invoiceFlag = Objects.equals(businessType,XbbRefTypeEnum.INVOICE.getCode());
                    boolean purchaseInvoiceFlag = Objects.equals(businessType,XbbRefTypeEnum.PURCHASE_INVOICE.getCode());
                    if (invoiceFlag || purchaseInvoiceFlag){
                        fieldList.forEach(field -> {
                            boolean isInvoiceFlag =  invoiceFlag && Objects.equals(field.getAttr(), InvoiceEnum.IS_CANCEL.getAttr());
                            boolean isPurchaseInvoiceFlag = purchaseInvoiceFlag && Objects.equals(field.getAttr(), PurchaseInvoiceEnum.IS_CANCEL.getAttr());
                            boolean flag = CollectionsUtil.isEmpty(field.getItems()) && (isInvoiceFlag || isPurchaseInvoiceFlag);
                            if (flag){
                                TempInvoiceEnum.initIsCancel(field);
                                TempPurchaseInvoiceEnum.initIsCancel(field);
                                item.setExplains(JSON.toJSONString(fieldList));
                                updatePaasFormExplainList.add(item);
                            }
                        });
                    }

                }
            });
            if (!CollectionUtils.isEmpty(updatePaasFormExplainList)){
                paasFormExplainModel.updateBatchExplains(updatePaasFormExplainList);
            }
            idGte = explainList.get(explainList.size() - 1).getId();
        }
        JSONObject object = new JSONObject();
        object.put("success", "成功");
        LOGGER.warn("consume:" + (DateTimeUtil.getInt() - start));
        LOGGER.warn("-------------repairInvoiceItemsExplain over-----------");
        return object.toJSONString();
    }

    /**
     * 退货退款：签订人，签订日期字段必填放开
     * @param paymentExplainDTO
     * @return
     * @throws XbbException
     */
    @RequestMapping(value = "/initRefundSetTypeExplain", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String initRefundSetTypeExplain(@RequestBody @Valid PaymentExplainDTO paymentExplainDTO) throws XbbException {
        if (!proBaseConfig.getXbbCode().equals(paymentExplainDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        LOGGER.warn("-------------initRefundSetTypeExplain begin-----------");
        long start = DateTimeUtil.getInt();
        LocaleContextHolder.setLocale(Locale.CHINA);

        //每次查询300条
        Long idGte = 0L;
        Integer startId = 0;
        Integer pageNum = 500;
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(StringConstant.DEL, 0);
        //param.put("corpid", "qwer1");
        param.put("businessTypeIn",Arrays.asList(XbbRefTypeEnum.REFUND.getCode()));
        Long maxId = paasFormExplainModel.getMaxId(param);
        param.put("start", startId);
        param.put("pageNum", pageNum);
        param.put("orderByStr", "id asc");
        while (true){
            param.put("idGte", idGte);
            //获取要处理的数据
            List<PaasFormExplainEntity> explainList = paasFormExplainModel.getNoHandleExplainsByFindEntitys(param);
            List<PaasFormExplainEntity> updatePaasFormExplainList = new ArrayList<>();
            LOGGER.warn("处理进度：已处理到 tb_paas_form_explain.id " + idGte + " / " + maxId);
            if (CollectionUtils.isEmpty(explainList)) {
                break;
            }
            explainList.forEach(item -> {
                if(!Objects.equals("[]",item.getExplains())){
                    List<FieldAttrEntity> fieldList = JsonHelperUtil.parseArray(item.getExplains(), FieldAttrEntity.class);
                    AtomicBoolean flag = new AtomicBoolean(false);
                    fieldList.forEach(field -> {
                        boolean isSingUserOrSignDate = Objects.equals(field.getAttr(),RefundEnum.SIGN_USER.getAttr()) || Objects.equals(field.getAttr(),RefundEnum.SIGN_DATE.getAttr());
                        if(isSingUserOrSignDate){
                            field.setSetType(SetTypeEnum.DISABLE_REPEAT.getCode());
                            item.setExplains(JSON.toJSONString(fieldList));
                            flag.set(true);
                        }
                    });
                    if (flag.get()) {
                        updatePaasFormExplainList.add(item);
                    }
                }
            });
            if (!CollectionUtils.isEmpty(updatePaasFormExplainList)){
                paasFormExplainModel.updateBatchExplains(updatePaasFormExplainList);
            }
            idGte = explainList.get(explainList.size() - 1).getId();
        }
        JSONObject object = new JSONObject();
        object.put("success", "成功");
        LOGGER.warn("consume:" + (DateTimeUtil.getInt() - start));
        LOGGER.warn("-------------initRefundSetTypeExplain over-----------");
        return object.toJSONString();
    }

    /**
     * 采购合同：采购字段的必填放开、未启用功能放开
     * @param paymentExplainDTO
     * @return
     * @throws XbbException
     */
    @RequestMapping(value = "/initPurchaseProductSetTypeExplain", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String initPurchaseProductSetTypeExplain(@RequestBody @Valid PaymentExplainDTO paymentExplainDTO) throws XbbException {
        if (!proBaseConfig.getXbbCode().equals(paymentExplainDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        LOGGER.warn("-------------initPurchaseProductSetTypeExplain begin-----------");
        long start = DateTimeUtil.getInt();
        LocaleContextHolder.setLocale(Locale.CHINA);

        //每次查询300条
        Long idGte = 0L;
        Integer startId = 0;
        Integer pageNum = 300;
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(StringConstant.DEL, 0);
        param.put("businessType",XbbRefTypeEnum.PURCHASE.getCode());
        Long maxId = paasFormExplainModel.getMaxId(param);
        param.put("start", startId);
        param.put("pageNum", pageNum);
        param.put("orderByStr", "id asc");
        while (true){
            param.put("idGte", idGte);
            //获取要处理的数据
            List<PaasFormExplainEntity> explainList = paasFormExplainModel.getNoHandleExplainsByFindEntitys(param);
            List<PaasFormExplainEntity> updatePaasFormExplainList = new ArrayList<>();
            LOGGER.warn("处理进度：已处理到 tb_paas_form_explain.id " + idGte + " / " + maxId);
            if (CollectionUtils.isEmpty(explainList)) {
                break;
            }
            explainList.forEach(item -> {
                if(!Objects.equals("[]",item.getExplains())){
                    List<FieldAttrEntity> fieldList = JsonHelperUtil.parseArray(item.getExplains(), FieldAttrEntity.class);
                    fieldList.forEach(field -> {
                        if (Objects.equals(field.getAttr(), PurchaseEnum.PRODUCT.getAttr())){
                            field.setIsForbidden(BasicConstant.ONE);
                            field.setSetType(BasicConstant.THREE);
                            item.setExplains(JSON.toJSONString(fieldList));
                            updatePaasFormExplainList.add(item);
                        }
                    });
                }
            });
            if (!CollectionUtils.isEmpty(updatePaasFormExplainList)){
                paasFormExplainModel.updateBatchExplains(updatePaasFormExplainList);
            }
            idGte = explainList.get(explainList.size() - 1).getId();
        }
        JSONObject object = new JSONObject();
        object.put("success", "成功");
        LOGGER.warn("consume:" + (DateTimeUtil.getInt() - start));
        LOGGER.warn("-------------initPurchaseProductSetTypeExplain over-----------");
        return object.toJSONString();
    }

    @RequestMapping(value = "/rollbackPurchaseProductSetTypeExplain", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String rollbackPurchaseProductSetTypeExplain(@RequestBody @Valid PaymentExplainDTO paymentExplainDTO) throws XbbException {
        if (!proBaseConfig.getXbbCode().equals(paymentExplainDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        LOGGER.warn("-------------rollbackPurchaseProductSetTypeExplain begin-----------");
        long start = DateTimeUtil.getInt();
        LocaleContextHolder.setLocale(Locale.CHINA);

        //每次查询300条
        Long idGte = 0L;
        Integer startId = 0;
        Integer pageNum = 300;
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(StringConstant.DEL, 0);
        param.put("businessType",XbbRefTypeEnum.PURCHASE.getCode());
        Long maxId = paasFormExplainModel.getMaxId(param);
        param.put("start", startId);
        param.put("pageNum", pageNum);
        param.put("orderByStr", "id asc");
        while (true){
            param.put("idGte", idGte);
            //获取要处理的数据
            List<PaasFormExplainEntity> explainList = paasFormExplainModel.getNoHandleExplainsByFindEntitys(param);
            List<PaasFormExplainEntity> updatePaasFormExplainList = new ArrayList<>();
            LOGGER.warn("处理进度：已处理到 tb_paas_form_explain.id " + idGte + " / " + maxId);
            if (CollectionUtils.isEmpty(explainList)) {
                break;
            }
            explainList.forEach(item -> {
                if(!Objects.equals("[]",item.getExplains())){
                    List<FieldAttrEntity> fieldList = JsonHelperUtil.parseArray(item.getExplains(), FieldAttrEntity.class);
                    fieldList.forEach(field -> {
                        if (Objects.equals(field.getAttr(), PurchaseEnum.PRODUCT.getAttr())){
                            field.setIsForbidden(BasicConstant.ZERO);
                            field.setSetType(BasicConstant.ONE);
                            item.setExplains(JSON.toJSONString(fieldList));
                            updatePaasFormExplainList.add(item);
                        }
                    });
                }
            });
            if (!CollectionUtils.isEmpty(updatePaasFormExplainList)){
                paasFormExplainModel.updateBatchExplains(updatePaasFormExplainList);
            }
            idGte = explainList.get(explainList.size() - 1).getId();
        }
        JSONObject object = new JSONObject();
        object.put("success", "成功");
        LOGGER.warn("consume:" + (DateTimeUtil.getInt() - start));
        LOGGER.warn("-------------rollbackPurchaseProductSetTypeExplain over-----------");
        return object.toJSONString();
    }
}
